iT邦幫忙

2022 iThome 鐵人賽

DAY 16
0
Modern Web

Fastify 101系列 第 16

[Fastify] Day16 - Content-Type Parser

  • 分享至 

  • xImage
  •  

大家好 我是 Yubin

當有一個 request 進來的時候,要如何去解析 (Parsing) 他帶過來的 Payload,會利用到 ContentTypeParser 這個東西。

Content-Type

Content-Type 是 HTTP Header 中的欄位,用來表達原始媒體類型 (media type)。

在 HTTP Header 中的表示語法如下:

Content-Type: text/html; charset=UTF-8

根據 Content-Type 的值不同,接收方可以做出相對應的行為來處理,例如根據不同的 type 選用不同的方式來解析進來的 Payload。

Media Type

Media Type,也被稱為 Multipurpose Internet Mail Extensions 或 MIME Type

常見的 MIME Type 可以參考這篇:MDN:Common MIME types

重要的 MIME Type:

  • application/octet-stream

二進位的預設類別,代表未知的二進制檔案,瀏覽器接收到通常不會執行會是會跳出詢問視窗。
如果 Content-Disposition 欄位被設定為 attachment,瀏覽器會提是下載的對話框。
可以參考 MDN:Content-Disposition

  • text/plain

文字檔案的預設類別。瀏覽器會愈設他們可以被呈現在畫面上。

要注意的是,text/plain 不代表任何一種文字檔案,如果用 text/plain 來傳 CSS 檔,瀏覽器不會把他當成 CSS 來解析。

  • text/css

要讓接收方的瀏覽器知道這個檔案是 CSS 檔,一定要用 text/css 這個 type,否則可能會被忽略。

  • text/html

表示該文件為 HTML 格式。

  • application/javascript

表示 JavaScript 文件。

  • application/json

表示 JSON 格式。

  • multipart/form-data

瀏覽器發送 HTML 表單時可以使用此類型。

image, audio, video, 等其他有的沒的 Media Type 可以參考 MDN:MIME

FastifyContentTypeParser

預設情況下,Fastify 只有 application/jsontext/plain 這兩種 Content-Type 的解析器,預設的字元編碼是 uft-8

收到其他 Content-Type 且沒有該 Parser 的時候,Fastify 會拋出 FST_ERR_CTP_INVALID_MEDIA_TYPE 的錯誤。

如果需要其他 ContentType Parser 的支援,可以透過 addContentTypeParser API 來進行擴充。
如果需要也可以把預設的 JSON Parser 或 Plain Parser 移除。

跟其他 API 或 Plugin 一樣,addContentTypeParser 被封裝在定義的 scope 內。
也就是說如果在 root 新增 parser,則整個 Fastify App 都可以使用,如果只定義在某個 Plugin 中,只有該 Plugin 可以使用該 Parser。

要注意的是,GETHEAD 這兩個 HTTP Method 的 Request Payload 永遠不會被解析。(因為他們不應該帶上 Payload。


要定義 ContentTypeParser 只需要透過 FastifyInstance 中的 .addContentTypeParser

import fastify, { FastifyInstance } from 'fastify'

const server: FastifyInstance = fastify()

server.addContentTypeParser('application/jsoff', function (request, payload, done) {
  jsoffParser(payload, function (err, body) {
    done(err, body)
  })
})

.addContentTypeParser()
第一個參數是 ContentType 的名稱,型態可以是 stringRegExpstring[]
第二個參數是 FastifyContentTypeParser,也就是定義 parsing 的動作。

可以對多個 ContentType 用同一個 Parser 來處理:

server.addContentTypeParser(['text/xml', 'application/xml'], function (request, payload, done) {
  xmlParser(payload, function (err, body) {
    done(err, body)
  })
})

或是透過正規表示式來套用到符合的 ContentType:

server.addContentTypeParser(/^image\/.*/, function (request, payload, done) {
  imageParser(payload, function (err, body) {
    done(err, body)
  })
})

  • removeContentTypeParser

可以移除一個或多個 Parser。

  • removeAllContentTypeParsers

移除當前所有存在的 Parser。


如果有要 match 到所有 ContentType 的需求,可以使用 * 來進行匹配。

server.addContentTypeParser('*', function (request, payload, done) {
  let data = ''
  payload.on('data', chunk => { data += chunk })
  payload.on('end', () => {
    done(null, data)
  })
})

雖然 Fastify 核心預設的 Parser 只有 application/jsontext/plain 這兩種,要處理其他 ContentType 都要自己定義 Parser,聽起來很麻煩。

但 Fastify 官方或社群,已經有寫好很多現成可以用的 Parser Plugin 了,只需要 npm install 再透過 server.register() 註冊就可以了。

例如:fastify-multipart


上一篇
[Fastify] Day15 - Logging
下一篇
[Fastify] Day17 - Validation and Serialization with Typebox
系列文
Fastify 10130
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言